/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package A1;

/**
 *
 * @author Mary Llenos
 * Grid class sets the horizontal and vertical streets for the traffic
 * simulation.  It will show the intersecting streets with 2 sets of
 * traffic lights and a number of random cars moving to the correct
 * direction.
 */
public class Grid {

    private ProjModel project;
    private TrafficLight tLight1;
    private TrafficLight tLight2;
    private char[][] grid;

    
    /**
     *Default empty constructor of Grid
     * 
     */
    public Grid(){
    }

    /**
     * Default constructor of Grid that accepts a ProjModel object
     * Instantiates new objects and initializes variables
     *
     * @param project
     */
    public Grid(ProjModel project) {
        this.tLight1 = new TrafficLight();
        this.tLight2 = new TrafficLight();
        this.project = project;
        int gs = project.getGridSize();   
        grid = new char[gs][gs];
        setAll('?');
    }

    /**
     * Sets all points of the Grid to the character passed to the method
     *
     * @param character
     */
    public void setAll(char character) {
        for (int row = 0; row < grid.length; row++) {
            char[] tempRow = grid[row];
            for (int column = 0; column < tempRow.length; column++) {
                grid[row][column] = character;
            }
        }
    }

    /**
     * Returns the character assigned to a specific point(row, column)
     * in the Grid
     *
     * @param row
     * @param column
     * @return char
     */
    public char gridValue(int row, int column) {
        return grid[row][column];
    }

    /**
     * Prints out all the characters in the Grid
     */
    public void show() {
        for (int r = 0; r < grid.length; r++) {
            char[] tempRow = grid[r];
            for (int column = 0; column < tempRow.length; column++) {
                char character = grid[r][column];
                System.out.print(character);
            }
            System.out.println("");
        }
    }

    /**
     * Returns the upper border (row) of the intersection
     *
     * @param number of horizontal lane
     * @return int
     */
    public int getMidV(int horizontalLaneNum){
        int nr = grid.length;
        int middle = 0;
        if (horizontalLaneNum == 1 || horizontalLaneNum ==2) middle = nr / 2+1;
        if (horizontalLaneNum == 3) middle = (nr/2)-1;
        return middle;
    }

    /**
     * Builds the horizontal street of the intersection
     *
     * @param number of horizontal lane
     */
     public void buildHorizontalStreet(int horizontalLaneNum) {
        int nr = grid.length;
        int laneNo = 0;
        int middle = 0;
        if (horizontalLaneNum == 1 || horizontalLaneNum ==2) middle = nr / 2;
        if (horizontalLaneNum == 3) middle = (nr/2)-2;
        for (int r = 0; r < nr; r++) {
            char[] row = grid[r];
            if (r == middle) {
                setRow(row, ' ');
                laneNo++;
                if (laneNo<horizontalLaneNum)
                middle++;
            }
        }
    }

     /**
      * Sets the lane(s) of the horizontal street with the received char ' '
      *
      * @param row
      * @param character
      */
    public void setRow(char[] row, char c) {
        for (int i = 0; i < row.length; i++) {
            row[i] = c;
        }
    }

    /**
     * Builds the horizontal streets border with '-'
     *
     * @param number of horizontal lane
     */
    public void buildHorizontalBorder(int horizontalLaneNum) {
        int nr = grid.length;
        int middle = 0;
        int border1 = 0;
        int border2 = 0;
        if (horizontalLaneNum == 1 || horizontalLaneNum ==2) middle = nr / 2;
        if (horizontalLaneNum == 3) middle = (nr/2)-2;
        border1 = middle - 1;
        border2 = border1 + horizontalLaneNum +1;
        for (int r = 0; r < nr; r++) {
            char[] row = grid[r];
            if (r == border1 || r == border2) {
                setRow(row, '-');
            }
        }
        tLight1.setRow(border1); // passes the upper horizontal border to set the horizontal traffic light
        tLight2.setRow(border2); // passes the lower horizontal border to set the vertical traffic light
    }

    /**
     * Returns the left border (column) of the intersection
     *
     * @param number of vertical lane
     * @return int
     */
    public int getMidH(int verticalLaneNum){
        int middle = 0;
        int nc = grid.length;
        if (verticalLaneNum == 1 || verticalLaneNum ==2) middle = nc / 2;
        if (verticalLaneNum == 3) middle = (nc/2)-1;
        if (verticalLaneNum ==4) middle = (nc/2)-2;
        return middle;
    }

    /**
     * Builds the vertical streets border with '|'
     *
     * @param number of vertical lane
     */
    public void buildVerticalBorder(int verticalLaneNum) {
        int nc = grid.length;
        int middle = 0;
        int border1 = 0;
        int border2 = 0;
        if (verticalLaneNum == 1 || verticalLaneNum ==2) middle = nc / 2;
        if (verticalLaneNum == 3) middle = (nc/2)-1;
        if (verticalLaneNum ==4) middle = (nc/2)-2;
        border1 = middle - 1;
        border2 = border1 + verticalLaneNum +1;
        for (int row = 0; row < grid.length; row++) {
            for (int column = 0; column < grid.length; column++) {
                    if (column == border1 || column == border2) {
                        grid[row][column] = '|';
                    }
            }
        }
        tLight1.setCol(border1); // passes the left vertical border to set the horizontal traffic light
        tLight2.setCol(border2); // passes the right vertical border to set the vertical traffic light
    }

    /**
     * Builds the spaces for the horizontal and vertical traffic light
     */
    public void buildTSpace(){
        int hRow = tLight1.getRow() - 3;
        int hCol = tLight1.getCol() - 3;
        int vRow = tLight2.getRow() + 1;
        int vCol = tLight2.getCol() + 1;

        for (int i = 0; i<3; i++){
            for (int j = 0; j<3; j++){
                grid[hRow][hCol] = ' ';
                hCol++;
                if (i == 1 && j == 0)
                    tLight1.setPos(hRow, hCol);
                }
        hRow++;
        hCol = tLight1.getCol() - 3;
        }

        for (int i = 0; i<3; i++){
            for (int j = 0; j<3; j++){
                grid[vRow][vCol] = ' ';
                vCol++;
                if (i == 1 && j == 0)
                    tLight2.setPos(vRow, vCol);
            }
        vRow++;
        vCol = tLight2.getCol() + 1;
        }
    }

    /**
     * Builds the traffic lights for the horizontal and vertical streets
     *
     * @param counter for the signals to change
     */
    public void buildTrafficLight(int counter){
        int hRow = tLight1.getRow();
        int hCol = tLight1.getCPos();
        int vRow = tLight2.getRow();
        int vCol = tLight2.getCPos();
        if (counter <5){
            grid[hRow][hCol] = tLight1.getSignal1();
            grid[vRow][vCol] = tLight2.getSignal3();
        }
        else {
            grid[hRow][hCol] = tLight1.getSignal2();
            grid[vRow][vCol] = tLight2.getSignal2();
            tLight1.changeSignal();
            tLight2.changeSignal();
        }
    }

    /**
     * Returns the current signal of the traffic light of the horizontal street
     * 
     * @return char
     */
    public char checkHTL(){
        int hRow = tLight1.getRow();
        int hCol = tLight1.getCPos();
        return grid[hRow][hCol];
    }

   /**
    * Returns the current signal of the traffic light of the vertical street
    * 
    * @return char
    */
    public char checkVTL(){
        int vRow = tLight2.getRow();
        int vCol = tLight2.getCPos();
        return grid[vRow][vCol];
    }

    /**
     * Builds the vertical street of the intersection
     *
     * @param number of vertical lane
     */
    public void buildVerticalStreet(int verticalLaneNum) {
        int nc = project.getGridSize();
        int middle = 0;
        for (int row = 0; row < grid.length; row++) {
            int laneNo = 0;
            if (verticalLaneNum == 1 || verticalLaneNum ==2) middle = nc / 2;
            if (verticalLaneNum == 3) middle = (nc/2)-1;
            if (verticalLaneNum ==4) middle = (nc/2)-2;
            for (int column = 0; column < grid.length; column++) {
                if (column == middle) {
                    grid[row][column] = ' ';
                    laneNo++;
                    if (laneNo<verticalLaneNum)
                        middle++;
                }
            }
        }
    }

    /**
     * Builds the car 'c' in the horizontal street
     * @param row
     * @param col
     */
    public void buildHCar(int row,int col){
        double prob = project.getProbCarHLane();
        if (prob !=0){
            grid[row][col] = 'c';
        }
    }

    /*
     * Deletes the previous position of car 'c/u' as it moves to the new 
     * position
     */
    public void deleteCar(int row, int col){
        grid[row][col] = ' ';
    }

    /**
     * Builds the car 'u' in the vertical street
     * @param row
     * @param col
     */
    public void buildVCar(int row, int col){
        double prob = project.getProbCarVLane();
        if (prob != 0){
            grid[row][col] = 'u';
        }
    }

    /**
     * Moves the car 'c' from previous position to its new position in the
     * horizontal street
     * 
     * @param row
     * @param col
     */
    public void moveHorCar (int row, int col){
        grid[row][col] = 'c';
        grid[row][col-1] = ' ';
    }

    /**
     * Moves the car to another lane to overtake a blocking wall/car
     * 
     * @param row
     * @param col
     */
    public void overtakeCar (int row, int col){
        grid[row][col] = 'o'; 
    }
    
    /**
     * Moves the car 'u' from previous position to its new position in the
     * vertical street
     * 
     * @param row
     * @param col
     */
    public void moveVerCar (int row, int col){
        grid[row][col] = 'u';
        grid[row+1][col] = ' ';
    }

    /**
     * Creates a wall/block in the vertical or horizontal street
     */
    public void createBlock (){
        int gs = project.getGridSize()/2;
        grid[gs+1][gs+1] = '-';
        grid[gs+1][gs] = '-';
    }
}